import React, { useEffect, useState, useRef } from "react";
import { useParams } from "react-router-dom";
import {
  Card,
  Breadcrumb,
  Tree,
  message,
  Tag,
  Pagination,
  Space,
  Table,
} from "antd";
import type { TreeDataNode, TableColumnsType } from "antd";

import {
  reqGetHospitalDepartmentList,
  reqGetHospitalDoctorList,
  reqGetHospitalScheduleRule,
} from "@/api/hospital/hospitalList";
import type {
  DepartmentList,
  BookingScheduleList,
  DoctorList,
  DepartmentItem,
  DoctorItem,
} from "@/api/hospital/hospitalList/types";

import "./Schedule.less";

export default function Schedule() {
  // 获取路由路径参数 - params
  const params = useParams();
  const hoscode = params.hoscode as string;
  // 1. 数据不涉及用户界面变化，所以没有定义成state。
  // 2. 用户界面更新时，希望值得到保留，所以使用 useRef
  const depcode = useRef("");
  const workDate = useRef("");
  const page = useRef(1);
  const limit = useRef(5);

  const [departmentList, setDepartmentList] = useState<DepartmentList>([]);
  // const [page, setPage] = useState(1);
  // const [limit, setLimit] = useState(5);
  const [scheduleList, setScheduleList] = useState<BookingScheduleList>([]);
  const [total, setTotal] = useState(0);
  const [doctorList, setDoctorList] = useState<DoctorList>([]);

  const [hosname, setHosname] = useState(""); // 医院名称
  const [depname, setDepname] = useState(""); // 科室名称

  // 获取科室列表
  // - async 函数返回值一定是 promise
  // - 这个 promise 对象的状态：
  //    - 如果 async 函数内部产生了失败状态的promise，就会失败
  //    - 如果 async 函数内部报错了，就会失败
  //    - 如果 async 函数内部全部执行完了没有出错，就会成功
  const getHospitalDepartmentList = async () => {
    const departmentList = await reqGetHospitalDepartmentList(hoscode);
    setDepartmentList(departmentList);
    const dep = (departmentList[0].children as DepartmentList)[0];
    depcode.current = dep.depcode;
    setDepname(dep.depname);

    // 收集所有需要展开的key
    setExpandedKeys(departmentList.map((item) => item.depcode));
  };

  // 获取排班列表
  const getHospitalScheduleRule = async () => {
    const res = await reqGetHospitalScheduleRule({
      page: page.current,
      limit: limit.current,
      hoscode,
      depcode: depcode.current,
    });
    setScheduleList(res.bookingScheduleList);
    setTotal(res.total);
    setHosname(res.baseMap.hosname);
    workDate.current = res.bookingScheduleList[0]?.workDate;
  };

  // 获取医生列表
  const getHospitalDoctorList = async () => {
    if (!workDate.current) {
      setDoctorList([]);
      message.warning("暂无数据");
      return;
    }
    const doctorList = await reqGetHospitalDoctorList({
      hoscode,
      depcode: depcode.current,
      workDate: workDate.current,
    });
    setDoctorList(doctorList);
  };

  useEffect(() => {
    // 获取数据
    const getData = async () => {
      // 1. 获取科室列表
      await getHospitalDepartmentList();
      // 2. 获取排班列表
      await getHospitalScheduleRule();
      // 3. 获取医生列表
      await getHospitalDoctorList();
    };
    getData();
  }, []);

  // 处理头部面包屑导航
  const formatBreadcrumb = () => {
    return [
      {
        title: hosname,
      },
      {
        title: depname,
      },
      {
        title: workDate.current,
      },
    ];
  };

  // 处理左侧科室数据
  const [expandedKeys, setExpandedKeys] = useState<string[]>([]);

  const formatDepartmentList = (
    departmentList: DepartmentList
  ): TreeDataNode[] => {
    return departmentList.map((dep: DepartmentItem) => {
      if (dep.children) {
        return {
          title: dep.depname,
          key: dep.depcode,
          children: formatDepartmentList(dep.children),
          disabled: true,
        };
      }
      return {
        title: dep.depname,
        key: dep.depcode,
      };
    });
  };

  const onSelect = async (selectedKeys: React.Key[], e: any) => {
    setDepname(e.node.title);
    depcode.current = selectedKeys[0] as string;
    await getHospitalScheduleRule();
    await getHospitalDoctorList();
  };

  // 排班
  const setWorkDate = (val: string) => {
    return async () => {
      // 不是state数据，更新不会让用户界面变化 --> 借助下面发送请求更新数据，从而间接更新workDate
      workDate.current = val;
      await getHospitalDoctorList();
    };
  };

  const handlePaginationChange = async (newPage: number, newLimit: number) => {
    page.current = newPage;
    limit.current = newLimit;
    await getHospitalScheduleRule();
    await getHospitalDoctorList();
  };

  // 医生列表
  const columns: TableColumnsType<DoctorItem> = [
    {
      title: "序号",
      key: "index",
      render(_, _record, index) {
        return <div>{index + 1}</div>;
      },
      align: "center",
    },
    {
      title: "医生",
      key: "docname",
      dataIndex: "docname",
      align: "center",
    },
    {
      title: "职称",
      key: "title",
      dataIndex: "title",
      align: "center",
    },
    {
      title: "号源时间",
      key: "workDate",
      dataIndex: "workDate",
      align: "center",
    },
    {
      title: "总预约数",
      key: "reservedNumber",
      dataIndex: "reservedNumber",
      align: "center",
    },
    {
      title: "剩余预约数",
      key: "availableNumber",
      dataIndex: "availableNumber",
      align: "center",
    },
    {
      title: "挂号费（元）",
      key: "amount",
      dataIndex: "amount",
      align: "center",
    },
    {
      title: "擅长技能",
      key: "skill",
      dataIndex: "skill",
    },
  ];

  return (
    <Card>
      <div>
        <div className="flex">
          <span>选择：</span>
          <Breadcrumb items={formatBreadcrumb()} />
        </div>
        <div className="flex">
          <div className="tree-container">
            <Tree
              treeData={formatDepartmentList(departmentList)}
              expandedKeys={expandedKeys}
              onSelect={onSelect}
              selectedKeys={[depcode.current]}
            />
          </div>
          <Space
            className="schedule-container"
            size="middle"
            direction="vertical"
          >
            <div>
              {scheduleList.map((schedule) => {
                return (
                  <Tag
                    key={schedule.workDate}
                    color={
                      schedule.workDate === workDate.current
                        ? "green"
                        : "default"
                    }
                    onClick={setWorkDate(schedule.workDate)}
                  >
                    <div>
                      {schedule.workDate} {schedule.dayOfWeek}
                    </div>
                    <div>
                      {schedule.availableNumber} / {schedule.reservedNumber}
                    </div>
                  </Tag>
                );
              })}
            </div>
            {workDate.current && (
              <Pagination
                total={total}
                pageSize={limit.current}
                pageSizeOptions={[5, 10, 15, 20]}
                onChange={handlePaginationChange}
              />
            )}
            {workDate.current && (
              <Table
                columns={columns}
                dataSource={doctorList}
                bordered
                rowKey="id"
                pagination={false}
              />
            )}
          </Space>
        </div>
      </div>
    </Card>
  );
}
